﻿using System.Security.Cryptography;
using System.Text;

namespace tools.algorithm
{
    /// <summary>
    /// AES 工具类（对称加密算法）
    /// </summary>
    public static class AesTool
    {
        /// <summary>
        /// 使用 AES 算法加密字符串
        /// </summary>
        /// <param name="key">密钥（分别支持 16、24、32 个十六进制字符）</param>
        /// <param name="iv">初始化向量（需为 16 个十六进制字符）</param>
        /// <param name="plainText">明文</param>
        /// <returns>密文</returns>
        public static string Encrypt(string? key, string? iv, string? plainText)
        {
            if (string.IsNullOrWhiteSpace(plainText))
            {
                return string.Empty;
            }

            Aes aes = Check(key, iv);
            var encryptor = aes.CreateEncryptor();
            aes.Dispose();

            using var ms = new MemoryStream();
            using var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
            using (var sw = new StreamWriter(cs))
            {
                sw.Write(plainText);
            }

            return Convert.ToBase64String(ms.ToArray());
        }

        /// <summary>
        /// 使用 AES 算法解密字符串
        /// </summary>
        /// <param name="key">密钥（分别支持 16、24、32 个十六进制字符）</param>
        /// <param name="iv">初始化向量（需为 16 个十六进制字符）</param>
        /// <param name="cipherText">密文</param>
        /// <returns>加密前的原文</returns>
        public static string Decrypt(string? key, string? iv, string? cipherText)
        {
            if (string.IsNullOrWhiteSpace(cipherText))
            {
                return string.Empty;
            }

            Aes aes = Check(key, iv);
            var decryptor = aes.CreateDecryptor();
            aes.Dispose();

            using var ms = new MemoryStream(Convert.FromBase64String(cipherText));
            using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
            using var sr = new StreamReader(cs);

            return sr.ReadToEnd();
        }

        /// <summary>
        /// 检查 AES 密钥和向量
        /// </summary>
        /// <param name="key">密钥（分别支持 16、24、32 个十六进制字符）</param>
        /// <param name="iv">初始化向量（需为 16 个十六进制字符）</param>
        /// <returns>Aes 实例</returns>
        private static Aes Check(string? key, string? iv)
        {
            ArgumentException.ThrowIfNullOrWhiteSpace(key);
            ArgumentException.ThrowIfNullOrWhiteSpace(iv);

            Aes aes = Aes.Create();
            aes.Key = Encoding.UTF8.GetBytes(key);
            aes.IV = Encoding.UTF8.GetBytes(iv);

            return aes;
        }
    }
}
